package com.juyu.miliao.scheduler.service.impl;


import com.alibaba.fastjson.JSONObject;
import com.juyu.miliao.common.constant.HomeVideoTypeConstant;
import com.juyu.miliao.common.domain.dto.HomeVideoCacheKeyDTO;
import com.juyu.miliao.common.util.CommonUtil;
import com.juyu.miliao.common.util.HomeVideoUtil;
import com.juyu.miliao.scheduler.dao.mysql.HomeVideoDao;
import com.juyu.miliao.scheduler.domin.UserVideo;
import com.juyu.miliao.scheduler.service.HomeVideoCacheService;
import com.juyu.miliao.scheduler.service.UpdateHomeVideoService;
import lombok.extern.log4j.Log4j2;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * @author jh
 * 2018/8/2
 */
@Log4j2
@Component
public class UpdateHomeVideoServiceImpl implements UpdateHomeVideoService {

    @Resource
    private HomeVideoDao homeVideoDao;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    private HomeVideoCacheService homeVideoCacheService;

    /**
     * 根据userId判断是否在视频中,有则更新视频信息
     *
     * @param userId userId
     */
    @Override
    public void updateByUserId(Long userId) {
        if (userId != 0 && userId > 0L) {
            updateByUserIdDetail(true, HomeVideoTypeConstant.ON_LINE, userId);
            updateByUserIdDetail(true, HomeVideoTypeConstant.VEST, userId);
            updateByUserIdDetail(false, HomeVideoTypeConstant.ON_LINE, userId);
            updateByUserIdDetail(false, HomeVideoTypeConstant.VEST, userId);
        }
    }

    private void updateByUserIdDetail(boolean recommend, String homeVideoType, Long userId) {
        HomeVideoCacheKeyDTO dto = HomeVideoUtil.getHomeVideoCacheKeyDTO(recommend, homeVideoType);
        String globalKey = homeVideoCacheService.getGlobalKey(dto.getJointGlobalKey());
        String reCacheKey = dto.getJointVideoKey() + globalKey;
        String reVideoRankKey = dto.getJointRankKey() + globalKey;
        String reVideoUserKey = dto.getJointUserKey() + globalKey;
        userVideoCache(reCacheKey, reVideoRankKey, reVideoUserKey, userId);
    }


    /**
     * 根据videoId判断是否在视频中,有则更新视频信息
     *
     * @param videoId videoId
     */
    @Override
    public void updateByVideoId(Long videoId) {
        if (videoId != null && videoId > 0L) {
            String id = String.valueOf(videoId);

            updateByVideoIdDetail(true, HomeVideoTypeConstant.ON_LINE, id);
            updateByVideoIdDetail(true, HomeVideoTypeConstant.VEST, id);
            updateByVideoIdDetail(false, HomeVideoTypeConstant.ON_LINE, id);
            updateByVideoIdDetail(false, HomeVideoTypeConstant.VEST, id);
        }
    }

    private void updateByVideoIdDetail(boolean recommend, String homeVideoType, String id) {
        HomeVideoCacheKeyDTO dto = HomeVideoUtil.getHomeVideoCacheKeyDTO(recommend, homeVideoType);
        String globalKey = homeVideoCacheService.getGlobalKey(dto.getJointGlobalKey());
        String reCacheKey = dto.getJointVideoKey() + globalKey;
        String reVideoRankKey = dto.getJointRankKey() + globalKey;
        videoRankCache(reCacheKey, reVideoRankKey, id);
    }


    /**
     * 操作redis更新videoId对应视频
     *
     * @param cacheKey     cacheKey
     * @param videoRankKey videoRankKey
     * @param videoId      videoId
     */
    private void videoRankCache(String cacheKey, String videoRankKey, String videoId) {
        //获取video的rank
        Long rank = stringRedisTemplate.opsForZSet().rank(videoRankKey, videoId);
        if (rank != null) {
            //新的video
            UserVideo newUserVideo = homeVideoDao.getVideoWithUser(CommonUtil.null2Long(videoId));
            //删除rank对应的cache
            stringRedisTemplate.opsForZSet().removeRange(cacheKey, rank, rank);
            //插入
            stringRedisTemplate.opsForZSet().add(cacheKey, JSONObject.toJSONString(newUserVideo), rank);
            //设定超时时间,有可能在这个插入的时候,定时器刚好刷新了
            stringRedisTemplate.expire(cacheKey, 10, TimeUnit.MINUTES);
        }
    }


    /**
     * 操作redis更新用户对应视频
     *
     * @param cacheKey     cacheKey
     * @param videoRankKey videoRankKey
     * @param videoUserKey videoUserKey
     * @param userId       userId
     */
    private void userVideoCache(String cacheKey, String videoRankKey, String videoUserKey, Long userId) {
        //置顶分数的user-video
        Set<String> userSet = stringRedisTemplate.opsForZSet().rangeByScore(videoUserKey, userId, userId);
        if (userSet != null && !userSet.isEmpty()) {
            for (String videoId : userSet) {
                videoRankCache(cacheKey, videoRankKey, videoId);
            }
        }
    }


}
